#include "znx_http_conn.h"


znx_bool_t
znx_http_conn_start_io(znx_http_conn_t *hc)
{
    if (hc->type == ZNX_HTTP_NET_CONN ||
        hc->type == ZNX_HTTP_SSL_CONN)
    {
        return znx_event_loop_start_io(hc->c);
    }

    return ZNX_FALSE;
}


znx_bool_t
znx_http_conn_stop_io(znx_http_conn_t *hc)
{
    if (hc->type == ZNX_HTTP_NET_CONN ||
        hc->type == ZNX_HTTP_SSL_CONN)
    {
        return znx_event_loop_stop_io(hc->c);
    }

    return ZNX_FALSE;
}


znx_bool_t
znx_http_conn_enable_read(znx_http_conn_t *hc)
{
    hc->read_active = 1;

    if (hc->type == ZNX_HTTP_NET_CONN ||
        hc->type == ZNX_HTTP_SSL_CONN)
    {
        return znx_event_loop_enable_read(hc->c);
    }

    return ZNX_FALSE;
}


znx_bool_t
znx_http_conn_disable_read(znx_http_conn_t *hc)
{
    hc->read_active = 0;
    return ZNX_TRUE;
}


znx_bool_t
znx_http_conn_read_ready(znx_http_conn_t *hc)
{
    if (hc->type == ZNX_HTTP_NET_CONN ||
        hc->type == ZNX_HTTP_SSL_CONN)
    {
        if (hc->c->read.schedule || hc->c->read.ready) {
            return ZNX_TRUE;
        }
        return ZNX_FALSE;
    }

    return ZNX_FALSE;
}


znx_bool_t
znx_http_conn_enable_write(znx_http_conn_t *hc)
{
    hc->write_active = 1;

    if (hc->type == ZNX_HTTP_NET_CONN ||
        hc->type == ZNX_HTTP_SSL_CONN)
    {
        return znx_event_loop_enable_write(hc->c);
    }

    return ZNX_FALSE;
}


znx_bool_t
znx_http_conn_disable_write(znx_http_conn_t *hc)
{
    hc->write_active = 0;
    return ZNX_TRUE;
}


znx_bool_t
znx_http_conn_write_ready(znx_http_conn_t *hc)
{
    if (hc->type == ZNX_HTTP_NET_CONN ||
        hc->type == ZNX_HTTP_SSL_CONN)
    {
        if (hc->c->write.schedule || hc->c->write.ready) {
            return ZNX_TRUE;
        }

        return ZNX_FALSE;
    }

    return ZNX_FALSE;
}


static void
znx_http_ssl_conn_close_handler(znx_conn_t *c)
{
    znx_http_conn_t *hc = c->data;

    if (c->ssl) {
        if (znx_ssl_shutdown(c) == ZNX_AGAIN) {
            c->ssl->handler = znx_http_ssl_conn_close_handler;
            return;
        }
    }

    znx_event_loop_remove_conn(c);
    znx_conn_free(c);
    hc->c = NULL;

    if (hc->close_handler) {
        hc->close_handler(hc);
    }
}


znx_result_t
znx_http_conn_close(znx_http_conn_t *hc)
{
    if (hc->type == ZNX_HTTP_NET_CONN ||
        hc->type == ZNX_HTTP_SSL_CONN)
    {
        if (hc->c->ssl) {
            if (znx_ssl_shutdown(hc->c) == ZNX_AGAIN) {
                hc->c->ssl->handler = znx_http_ssl_conn_close_handler;
                return ZNX_AGAIN;
            }
        }

        znx_event_loop_remove_conn(hc->c);
        znx_conn_free(hc->c);
        hc->c = NULL;
        return ZNX_SUCCESS;
    }

    return ZNX_FALSE;
}


static void
znx_http_net_conn_event(znx_http_conn_t *hc, znx_event_t *event)
{
    if (event == &hc->c->read) {
        if (hc->read_active) {
            hc->read_handler(hc);
            return;
        }

        znx_event_loop_disable_read(hc->c);
        return;
    }

    if (hc->write_active) {
        hc->write_handler(hc);
        return;
    }

    znx_event_loop_disable_write(hc->c);
}


void
znx_http_net_conn_event_handler(znx_event_t *event)
{
    znx_conn_t              *c;
    znx_http_conn_t         *hc;

    c = event->data;
    hc = c->data;

    if (hc->type == ZNX_HTTP_NET_CONN ||
        hc->type == ZNX_HTTP_SSL_CONN)
    {
        znx_http_net_conn_event(hc, event);
        return;
    }

    return;
}


znx_result_t
znx_http_conn_read(znx_http_conn_t *hc, void *buf, size_t count)
{
    if (hc->type == ZNX_HTTP_NET_CONN) {
        return znx_conn_read(hc->c, buf, count);
    }

    if (hc->type == ZNX_HTTP_SSL_CONN) {
        return znx_ssl_read(hc->c, buf, count);
    }

    return ZNX_FAILED;
}


znx_result_t
znx_http_conn_readv(znx_http_conn_t *hc, znx_iovec_t *vector, int count)
{
    if (hc->type == ZNX_HTTP_NET_CONN) {
        return znx_conn_readv(hc->c, vector, count);
    }

    if (hc->type == ZNX_HTTP_SSL_CONN) {
        return znx_ssl_readv(hc->c, vector, count);
    }

    return ZNX_FAILED;
}


znx_result_t
znx_http_conn_write(znx_http_conn_t *hc, void *buf, size_t count)
{
    if (hc->type == ZNX_HTTP_NET_CONN) {
        return znx_conn_write(hc->c, buf, count);
    }

    if (hc->type == ZNX_HTTP_SSL_CONN) {
        return znx_ssl_write(hc->c, buf, count);
    }

    return ZNX_FAILED;
}


znx_result_t
znx_http_conn_writev(znx_http_conn_t *hc, znx_iovec_t *vector, int count)
{
    if (hc->type == ZNX_HTTP_NET_CONN) {
        return znx_conn_writev(hc->c, vector, count);
    }

    if (hc->type == ZNX_HTTP_SSL_CONN) {
        return znx_ssl_writev(hc->c, vector, count);
    }

    return ZNX_FAILED;
}